﻿
Imports System.Threading

Public Class eventCombAsyncOperation
    Inherits eventComb
    Private _ao As async_operation = Nothing

    <Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.NoInlining)> _
    Private Sub New(ByVal d As _do(Of Boolean))
        MyBase.New(New _do(Of Boolean)() {assert_return(Not d Is Nothing, d)}, 2)
        timeouted = Sub()
                        wait_when(Function() _ao Is Nothing)
                        ao().force_finish()
                    End Sub
        resetting = Sub()
                        _ao = Nothing
                    End Sub
    End Sub

    <Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.NoInlining)> _
    Public Sub New(ByVal begin As _do(Of AsyncCallback, Object, IAsyncResult),
                   ByVal [end] As void(Of IAsyncResult))
        Me.New(step1(begin, [end]))
    End Sub

    <Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.NoInlining)> _
    Public Shared Function ctor(Of T)(ByVal begin As _do(Of AsyncCallback, Object, IAsyncResult),
                                      ByVal [end] As _do(Of IAsyncResult, T),
                                      Optional ByVal result As pointer(Of T) = Nothing) As eventCombAsyncOperation
        Return New eventCombAsyncOperation(step1(begin, [end], result))
    End Function

    Private Function ao() As async_operation
        assert(Not _ao Is Nothing)
        Return _ao
    End Function

    Private Sub _assert()
        assert(_ao Is Nothing)
    End Sub

    Public Shared Shadows Property current() As eventCombAsyncOperation
        Get
            Return convertor.cast(Of eventCombAsyncOperation)(eventComb.current())
        End Get
        Private Set(ByVal value As eventCombAsyncOperation)
            eventComb.current() = value
        End Set
    End Property

    Private Shared Function step1(ByVal begin As _do(Of AsyncCallback, Object, IAsyncResult),
                                  ByVal [end] As void(Of IAsyncResult)) As _do(Of Boolean)
        If [end] Is Nothing Then
            Return do_(True)
        Else
            Return step1(begin,
                         async_operation.void_to_do([end]),
                         Nothing)
        End If
    End Function

    Private Shared Function step1(Of T)(ByVal begin As _do(Of AsyncCallback, Object, IAsyncResult),
                                        ByVal [end] As _do(Of IAsyncResult, T),
                                        ByVal result As pointer(Of T)) As _do(Of Boolean)
        If begin Is Nothing OrElse [end] Is Nothing Then
            Return do_(True)
        Else
            Return Function() As Boolean
                       Dim this As eventCombAsyncOperation = Nothing
                       this = current()
                       this._assert()
                       this._ao = async_operation.ctor(
                                      begin,
                                      Function(ByRef a)
                                          Dim inAsyncThread As Boolean = False
                                          inAsyncThread = eventComb.notInEventCombThread()
                                          Dim rst As T = Nothing
                                          If inAsyncThread Then
                                              current() = this
                                          End If
                                          Try
                                              rst = [end](a)
                                          Finally
                                              If inAsyncThread Then
                                                  current() = Nothing
                                              End If
                                          End Try
                                          Return rst
                                      End Function,
                                      Sub(ByRef isuc As Boolean)
                                          Dim suc As Boolean = False
                                          suc = isuc
                                          'the callback could happen in the same thread as begin method called.
                                          this.locked(
                                              Sub()
                                                  If Not suc Then
                                                      this.mark_as_failed()
                                                  End If
                                                  If eventComb.notInEventCombThread() Then
                                                      [resume](this)
                                                  End If
                                              End Sub)
                                      End Sub,
                                      result,
                                      this.callstack())
                       If this.ao().begin_succeeded() Then
                           If Not this.ao().finished() Then
                               this.inc_pends()
                           End If
                           Return goto_end()
                       Else
                           Return False
                       End If
                   End Function
        End If
    End Function
End Class
